package com.admin.system.modules.system.rest;

import com.admin.common.constant.Constant;
import com.admin.common.constant.ExceptionConstant;
import com.admin.common.entity.BaseEntity;
import com.admin.common.exception.BadRequestException;
import com.admin.common.utils.PageResult;
import com.admin.component.web.MultipartFileUtil;
import com.admin.core.dto.UserPasswordDTO;
import com.admin.core.dto.UserQueryDTO;
import com.admin.core.entity.SysJob;
import com.admin.core.entity.SysRole;
import com.admin.core.entity.SysUser;
import com.admin.logging.annotation.Log;
import com.admin.logging.enums.OperateTypeEnum;
import com.admin.oauth.util.LoginUserUtil;
import com.admin.system.modules.system.service.UserService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author sq-lan
 */
@Api(tags = "系统：用户管理")
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {

    private final PasswordEncoder passwordEncoder;
    private final UserService userService;

    @ApiOperation("查询用户")
    @GetMapping
    @PreAuthorize("@ss.check('user:list')")
    public ResponseEntity<PageResult<SysUser>> paging(UserQueryDTO dto) {
        return new ResponseEntity<>(userService.paging(dto), HttpStatus.OK);
    }

    @Log(module = "用户管理", operateType = OperateTypeEnum.ADD)
    @ApiOperation("新增用户")
    @PostMapping
    @PreAuthorize("@ss.check('user:add')")
    public ResponseEntity<Object> add(@Validated @RequestBody SysUser entity) {
        if (entity.getId() != null) {
            throw new BadRequestException(ExceptionConstant.ERROR_PARAM);
        }
        entity.setPassword(passwordEncoder.encode(Constant.DEFAULT_PASSWORD));
        userService.add(entity);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }

    @Log(module = "用户管理", operateType = OperateTypeEnum.MODIFY)
    @ApiOperation("修改用户")
    @PutMapping
    @PreAuthorize("@ss.check('user:edit')")
    public ResponseEntity<Object> modify(@Validated(BaseEntity.Update.class) @RequestBody SysUser entity) throws Exception {
        userService.modify(entity);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @Log(module = "用户管理", operateType = OperateTypeEnum.REMOVE)
    @ApiOperation("删除用户")
    @DeleteMapping
    @PreAuthorize("@ss.check('user:del')")
    public ResponseEntity<Object> remove(@RequestBody Set<Integer> ids) {
        userService.remove(ids);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @ApiOperation("导出用户数据")
    @GetMapping(value = "/download")
    @PreAuthorize("@ss.check('user:list')")
    public void export(HttpServletResponse response, UserQueryDTO dto) throws IOException {
        List<SysUser> users = userService.list(dto);
        List<Map<String, Object>> list = new ArrayList<>();
        for (SysUser user : users) {
            List<String> roles = user.getRoles().stream().map(SysRole::getName).collect(Collectors.toList());
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("用户名", user.getUsername());
            map.put("角色", roles);
            map.put("部门", user.getDept().getName());
            map.put("岗位", user.getJobs().stream().map(SysJob::getName).collect(Collectors.toList()));
            map.put("邮箱", user.getEmail());
            map.put("状态", user.getEnabled() ? "启用" : "禁用");
            map.put("手机号码", user.getPhone());
            map.put("修改密码的时间", user.getPwdResetTime());
            map.put("创建日期", user.getCreateTime());
            list.add(map);
        }
        MultipartFileUtil.downloadExcel(list, response);
    }

    @Log(module = "用户管理", operateType = OperateTypeEnum.MODIFY, description = "重置密码")
    @ApiOperation("重置密码")
    @PutMapping(value = "/resetPwd")
    public ResponseEntity<Object> resetPwd(@RequestBody Set<Integer> ids) {
        String pwd = passwordEncoder.encode(Constant.DEFAULT_PASSWORD);
        userService.update(Wrappers.<SysUser>lambdaUpdate().in(SysUser::getId, ids).set(SysUser::getPassword, pwd));
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @Log(module = "用户管理", operateType = OperateTypeEnum.MODIFY, description = "个人中心修改用户")
    @ApiOperation("修改用户：个人中心")
    @PutMapping(value = "center")
    public ResponseEntity<Object> modifyMy(@Validated(BaseEntity.Update.class) @RequestBody SysUser entity) {
        if (!entity.getId().equals(LoginUserUtil.userId())) {
            throw new BadRequestException(ExceptionConstant.PERMISSION_DENIED);
        }
        userService.modifyMy(entity);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @Log(module = "用户管理", operateType = OperateTypeEnum.MODIFY, description = "修改密码")
    @ApiOperation("修改密码")
    @PostMapping(value = "/updatePass")
    public ResponseEntity<Object> updatePassword(@RequestBody UserPasswordDTO dto) throws Exception {
        userService.updatePassword(dto);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @Log(module = "用户管理", operateType = OperateTypeEnum.MODIFY, description = "修改头像")
    @ApiOperation("修改头像")
    @PostMapping(value = "/updateAvatar")
    public ResponseEntity<Object> updateUserAvatar(@RequestParam MultipartFile avatar) {
        return new ResponseEntity<>(userService.updateAvatar(avatar), HttpStatus.OK);
    }

    @Log(module = "用户管理", operateType = OperateTypeEnum.MODIFY, description = "修改邮箱")
    @ApiOperation("修改邮箱")
    @PostMapping(value = "/updateEmail/{code}")
    public ResponseEntity<Object> updateEmail(@PathVariable String code, @RequestBody SysUser entity) throws Exception {
        userService.updateEmail(code, entity);
        return new ResponseEntity<>(HttpStatus.OK);
    }

}
